#ifndef __hex_hh__
#define __hex_hh__

class Hex
{
public:
  Hex() {}
  virtual ~Hex() {}
  virtual double* evaluate_basis ( int n_points, const double points[] ) = 0 ;
  virtual double* evaluate_gradient ( int n_points, const double points[] ) = 0 ;

  virtual int test() = 0 ;
  
//  double* barycentric_coords ( double p[3] ) ;
  virtual double element_volume () ;

protected:
  const double* vertices ;
  double volume;

private:
  void compute_volume() ;

};

inline
double Hex::element_volume()
{
  return volume;
}

inline
void Hex::compute_volume()
{
}


class Hex8 : public Hex
{
public:
  Hex8() : Hex() {}
  virtual double* evaluate_basis ( int n_points, const double points[] ) ;
  virtual double* evaluate_gradient ( int n_points, const double points[] ) ;

  virtual int test() ;
  
private:
  // the natural coordinates of the HEX element.
  static const double reference_points[3*8] ;
};


class Hex20 : public Hex
{
public:
  Hex20() : Hex() {}
  virtual double* evaluate_basis ( int n_points, const double points[] ) ;
  virtual double* evaluate_gradient ( int n_points, const double points[] ) ;

  virtual int test() ;
  
private:
  // the natural coordinates of the HEX element.
  static const double reference_points[3*20] ;
};


class Hex27 : public Hex
{
public:
  Hex27() : Hex() {}
  virtual double* evaluate_basis ( int n_points, const double points[] ) ;
  virtual double* evaluate_gradient ( int n_points, const double points[] ) {return 0;}

  virtual int test() ;
  
private:
  // the natural coordinates of the HEX element.
  static const double reference_points[3*27] ;
};



#endif // #ifndef __hex_hh__
